home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / djgpp / src / gas-211 / gas / subsegs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-30  |  10.4 KB  |  395 lines

  1. /* subsegs.c - subsegments -
  2.    Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
  3.  
  4.    This file is part of GAS, the GNU Assembler.
  5.  
  6.    GAS is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    GAS is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with GAS; see the file COPYING.  If not, write to
  18.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Segments & sub-segments.
  22.  */
  23.  
  24. #include "as.h"
  25.  
  26. #include "subsegs.h"
  27. #include "obstack.h"
  28.  
  29. frchainS *frchain_root, *frchain_now;
  30.  
  31. #ifndef BFD_ASSEMBLER
  32. #ifdef MANY_SEGMENTS
  33. segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
  34.  
  35. #else
  36. /* Commented in "subsegs.h". */
  37. frchainS *data0_frchainP, *bss0_frchainP;
  38.  
  39. #endif /* MANY_SEGMENTS */
  40. char *CONST seg_name[] =
  41. {
  42.   "absolute",
  43. #ifdef MANY_SEGMENTS
  44.   "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
  45. #else
  46.   "text",
  47.   "data",
  48.   "bss",
  49. #endif /* MANY_SEGMENTS */
  50.   "unknown",
  51.   "absent",
  52.   "pass1",
  53.   "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
  54.   "bignum/flonum",
  55.   "difference",
  56.   "debug",
  57.   "transfert vector preload",
  58.   "transfert vector postload",
  59.   "register",
  60.   "",
  61. };                /* Used by error reporters, dumpers etc. */
  62. #endif /* BFD_ASSEMBLER */
  63.  
  64.  
  65. void
  66. subsegs_begin ()
  67. {
  68.   /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
  69. #if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
  70.   know (SEG_ABSOLUTE == 0);
  71.   know (SEG_TEXT == 1);
  72.   know (SEG_DATA == 2);
  73.   know (SEG_BSS == 3);
  74.   know (SEG_UNKNOWN == 4);
  75.   know (SEG_ABSENT == 5);
  76.   know (SEG_PASS1 == 6);
  77.   know (SEG_GOOF == 7);
  78.   know (SEG_BIG == 8);
  79.   know (SEG_DIFFERENCE == 9);
  80.   know (SEG_DEBUG == 10);
  81.   know (SEG_NTV == 11);
  82.   know (SEG_PTV == 12);
  83.   know (SEG_REGISTER == 13);
  84.   know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER);
  85. #endif
  86.  
  87.   obstack_begin (&frags, 5000);
  88.   frchain_root = NULL;
  89.   frchain_now = NULL;        /* Warn new_subseg() that we are booting. */
  90.   /* Fake up 1st frag.  It won't be used=> is ok if obstack...
  91.      pads the end of it for alignment. */
  92.   frag_now = (fragS *) obstack_alloc (&frags, SIZEOF_STRUCT_FRAG);
  93.   memset (frag_now, SIZEOF_STRUCT_FRAG, 0);
  94.  
  95. #ifndef BFD_ASSEMBLER
  96.   /* This 1st frag will not be in any frchain.
  97.      We simply give subseg_new somewhere to scribble. */
  98.   now_subseg = 42;        /* Lie for 1st call to subseg_new. */
  99. #ifdef MANY_SEGMENTS
  100.   {
  101.     int i;
  102.     for (i = SEG_E0; i < SEG_UNKNOWN; i++)
  103.       {
  104.     subseg_new (i, 0);
  105.     segment_info[i].frchainP = frchain_now;
  106.       }
  107.   }
  108. #else
  109.   subseg_new (SEG_DATA, 0);    /* .data 0 */
  110.   data0_frchainP = frchain_now;
  111.  
  112.   subseg_new (SEG_BSS, 0);
  113.   bss0_frchainP = frchain_now;
  114.  
  115. #endif /* ! MANY_SEGMENTS */
  116. #endif /* ! BFD_ASSEMBLER */
  117.  
  118. }
  119.  
  120. /*
  121.  *            subseg_change()
  122.  *
  123.  * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
  124.  * subsegment. If we are already in the correct subsegment, change nothing.
  125.  * This is used eg as a worker for subseg_new [which does make a new frag_now]
  126.  * and for changing segments after we have read the source. We construct eg
  127.  * fixSs even after the source file is read, so we do have to keep the
  128.  * segment context correct.
  129.  */
  130. void
  131. subseg_change (seg, subseg)
  132.      register segT seg;
  133.      register int subseg;
  134. {
  135.   now_seg = seg;
  136.   now_subseg = subseg;
  137.  
  138. #ifdef BFD_ASSEMBLER
  139.   {
  140.     segment_info_type *seginfo;
  141.     seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
  142.     if (! seginfo)
  143.       {
  144.     seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
  145.     if (! seginfo)
  146.       abort ();
  147.     seginfo->fix_root = 0;
  148.     seginfo->fix_tail = 0;
  149.     seginfo->bfd_section = seg;
  150.     bfd_set_section_userdata (stdoutput, seg, (char *) seginfo);
  151.       }
  152.   }
  153. #else
  154. #ifdef MANY_SEGMENTS
  155.   seg_fix_rootP = &segment_info[seg].fix_root;
  156.   seg_fix_tailP = &segment_info[seg].fix_tail;
  157. #else
  158.   if (seg == SEG_DATA)
  159.     {
  160.       seg_fix_rootP = &data_fix_root;
  161.       seg_fix_tailP = &data_fix_tail;
  162.     }
  163.   else if (seg == SEG_TEXT)
  164.     {
  165.       seg_fix_rootP = &text_fix_root;
  166.       seg_fix_tailP = &text_fix_tail;
  167.     }
  168.   else
  169.     {
  170.       know (seg == SEG_BSS);
  171.       seg_fix_rootP = &bss_fix_root;
  172.       seg_fix_tailP = &bss_fix_tail;
  173.     }
  174.  
  175. #endif
  176. #endif
  177. }
  178.  
  179. static void
  180. subseg_new_rest (seg, subseg)
  181.      segT seg;
  182.      subsegT subseg;
  183. {
  184.   long tmp;            /* JF for obstack alignment hacking */
  185.   register frchainS *frcP;    /* crawl frchain chain */
  186.   register frchainS **lastPP;    /* address of last pointer */
  187.   frchainS *newP;        /* address of new frchain */
  188.   register fragS *former_last_fragP;
  189.   register fragS *new_fragP;
  190.  
  191.   if (frag_now)        /* If not bootstrapping. */
  192.     {
  193.       frag_now->fr_fix = obstack_next_free (&frags) - frag_now->fr_literal;
  194.       frag_wane (frag_now);    /* Close off any frag in old subseg. */
  195.     }
  196.   /*
  197.    * It would be nice to keep an obstack for each subsegment, if we swap
  198.    * subsegments a lot. Hence we would have much fewer frag_wanes().
  199.    */
  200.   {
  201.     obstack_finish (&frags);
  202.     /*
  203.      * If we don't do the above, the next object we put on obstack frags
  204.      * will appear to start at the fr_literal of the current frag.
  205.      * Also, above ensures that the next object will begin on a
  206.      * address that is aligned correctly for the engine that runs
  207.      * this program.
  208.      */
  209.   }
  210.   subseg_change (seg, (int) subseg);
  211.   /*
  212.    * Attempt to find or make a frchain for that sub seg.
  213.    * Crawl along chain of frchainSs, begins @ frchain_root.
  214.    * If we need to make a frchainS, link it into correct
  215.    * position of chain rooted in frchain_root.
  216.    */
  217.   for (frcP = *(lastPP = &frchain_root);
  218.        frcP && (int) (frcP->frch_seg) <= (int) seg;
  219.        frcP = *(lastPP = &frcP->frch_next))
  220.     {
  221.       if ((int) (frcP->frch_seg) == (int) seg
  222.       && frcP->frch_subseg >= subseg)
  223.     {
  224.       break;
  225.     }
  226.     }
  227.   /*
  228.    * frcP:        Address of the 1st frchainS in correct segment with
  229.    *        frch_subseg >= subseg.
  230.    *        We want to either use this frchainS, or we want
  231.    *        to insert a new frchainS just before it.
  232.    *
  233.    *        If frcP==NULL, then we are at the end of the chain
  234.    *        of frchainS-s. A NULL frcP means we fell off the end
  235.    *        of the chain looking for a
  236.    *        frch_subseg >= subseg, so we
  237.    *        must make a new frchainS.
  238.    *
  239.    *        If we ever maintain a pointer to
  240.    *        the last frchainS in the chain, we change that pointer
  241.    *        ONLY when frcP==NULL.
  242.    *
  243.    * lastPP:    Address of the pointer with value frcP;
  244.    *        Never NULL.
  245.    *        May point to frchain_root.
  246.    *
  247.    */
  248.   if (!frcP
  249.       || ((int) (frcP->frch_seg) > (int) seg
  250.       || frcP->frch_subseg > subseg))    /* Kinky logic only works with 2 segments. */
  251.     {
  252.       /*
  253.        * This should be the only code that creates a frchainS.
  254.        */
  255.       newP = (frchainS *) obstack_alloc (&frags, sizeof (frchainS));
  256.       memset (newP, sizeof (frchainS), 0);
  257.       /* This begines on a good boundary because a obstack_done()
  258.      preceeded it.  It implies an obstack_done(), so we expect
  259.      the next object allocated to begin on a correct boundary. */
  260.       *lastPP = newP;
  261.       newP->frch_next = frcP;    /* perhaps NULL */
  262.       (frcP = newP)->frch_subseg = subseg;
  263.       newP->frch_seg = seg;
  264.       newP->frch_last = NULL;
  265.     }
  266.   /*
  267.    * Here with frcP ->ing to the frchainS for subseg.
  268.    */
  269.   frchain_now = frcP;
  270.   /*
  271.    * Make a fresh frag for the subsegment.
  272.    */
  273.   /* We expect this to happen on a correct boundary since it was
  274.      proceeded by a obstack_done(). */
  275.   tmp = obstack_alignment_mask (&frags);    /* JF disable alignment */
  276.   obstack_alignment_mask (&frags) = 0;
  277.   frag_now = (fragS *) obstack_alloc (&frags, SIZEOF_STRUCT_FRAG);
  278.   obstack_alignment_mask (&frags) = tmp;
  279.   /* But we want any more chars to come immediately after the
  280.      structure we just made. */
  281.   new_fragP = frag_now;
  282.   new_fragP->fr_next = NULL;
  283.   /*
  284.    * Append new frag to current frchain.
  285.    */
  286.   former_last_fragP = frcP->frch_last;
  287.   if (former_last_fragP)
  288.     {
  289.       know (former_last_fragP->fr_next == NULL);
  290.       know (frchain_now->frch_root);
  291.       former_last_fragP->fr_next = new_fragP;
  292.     }
  293.   else
  294.     {
  295.       frcP->frch_root = new_fragP;
  296.     }
  297.   frcP->frch_last = new_fragP;
  298. }
  299.  
  300. /*
  301.  *            subseg_new()
  302.  *
  303.  * If you attempt to change to the current subsegment, nothing happens.
  304.  *
  305.  * In:    segT, subsegT code for new subsegment.
  306.  *    frag_now -> incomplete frag for current subsegment.
  307.  *    If frag_now==NULL, then there is no old, incomplete frag, so
  308.  *    the old frag is not closed off.
  309.  *
  310.  * Out:    now_subseg, now_seg updated.
  311.  *    Frchain_now points to the (possibly new) struct frchain for this
  312.  *    sub-segment.
  313.  *    Frchain_root updated if needed.
  314.  */
  315.  
  316. #ifndef BFD_ASSEMBLER
  317. void
  318. subseg_new (seg, subseg)    /* begin assembly for a new sub-segment */
  319.      register segT seg;        /* SEG_DATA or SEG_TEXT */
  320.      register subsegT subseg;
  321. {
  322. #ifndef MANY_SEGMENTS
  323.   know (seg == SEG_DATA || seg == SEG_TEXT || seg == SEG_BSS);
  324. #endif
  325.  
  326. #ifdef OBJ_AOUT
  327.   /* If -R specifed, always put stuff into the data section */
  328.   if (flagseen['R'])
  329.     {
  330.       if (seg == SEG_DATA)
  331.     {
  332.       subseg += 1000;
  333.       seg = SEG_TEXT;
  334.     }
  335.     }
  336. #endif
  337.  
  338.   if (seg != now_seg || subseg != now_subseg)
  339.     {                /* we just changed sub-segments */
  340.       subseg_new_rest (seg, subseg);
  341.     }
  342. }
  343.  
  344. #else /* BFD_ASSEMBLER */
  345.  
  346. segT
  347. subseg_new (segname, subseg)
  348.      char *segname;
  349.      subsegT subseg;
  350. {
  351.   segT secptr;
  352.   segment_info_type *seginfo;
  353.   const char *now_seg_name = (now_seg
  354.                   ? bfd_get_section_name (stdoutput, now_seg)
  355.                   : 0);
  356.  
  357.   if (now_seg_name
  358.       && (now_seg_name == segname
  359.       || !strcmp (now_seg_name, segname))
  360.       && subseg == now_subseg)
  361.     return now_seg;
  362.  
  363.   secptr = bfd_make_section_old_way (stdoutput, segname);
  364.   seginfo = seg_info (secptr);
  365.   if (! seginfo)
  366.     {
  367.       secptr->output_section = secptr;
  368.       seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
  369.       if (!seginfo)
  370.     abort ();
  371.       seginfo->fix_root = 0;
  372.       seginfo->fix_tail = 0;
  373.       seginfo->bfd_section = secptr;
  374.       bfd_set_section_userdata (stdoutput, secptr, (char *) seginfo);
  375.       subseg_new_rest (secptr, subseg);
  376.       seginfo->frchainP = frchain_now;
  377.     }
  378.   else
  379.     subseg_new_rest (secptr, subseg);
  380.   return secptr;
  381. }
  382.  
  383. void
  384. subseg_set (secptr, subseg)
  385.      segT secptr;
  386.      subsegT subseg;
  387. {
  388.   if (! (secptr == now_seg && subseg == now_subseg))
  389.     subseg_new_rest (secptr, subseg);
  390. }
  391.  
  392. #endif /* BFD_ASSEMBLER */
  393.  
  394. /* end of subsegs.c */
  395.